/*!
    \file  main.c
    \brief enet demo 
*/

/*
    Copyright (C) 2016 GigaDevice

    2016-10-19, V1.0.0, demo for GD32F4xx
*/

#include "gd32f4xx.h"
#include "netconf/netconf.h"
#include "main.h"
#include "lwip/tcp.h"
#include "lwip/lwip_timers.h"
#include "gd32f450z_eval.h"
#include "hello_gigadevice/hello_gigadevice.h"
#include "udp_echo/udp_echo.h"
#include "tcp_client/tcp_client.h"
#include "cli/cli_setup.h"
#include "cm_backtrace/cm_backtrace.h"
#include "uart/effective_printf.h"
#include "uart/uart_dma.h"
#include "project_config/project_config.h"
#include "system_config/system_config.h"
#include "uart/board_uart.h"
#include "build_info/build_info.h"
#include "led/led.h"

#define SYSTEMTICK_PERIOD_MS  10

__IO uint32_t g_localtime = 0; /* for creating a time reference incremented by 10ms */
uint32_t g_timedelay;

static uint64_t uptime = 0;
static uint64_t pps_timestamp = 0;

static void task_in_pps(void);

/*!
    \brief      main function
    \param[in]  none
    \param[out] none
    \retval     none
*/
int main(void) {
    nvic_vector_table_set(NVIC_VECTTAB_FLASH, 0x00020000);
    led_init();
    led_breath(1);

    board_uart_init();
    uart_dma_init();

    show_build_info();

    printf("UART init done\r\n");

    setupCli();
    printf("CLI init done\r\n");

    system_config_init();
    printf("system config init done\r\n");

    gd_eval_key_init(KEY_TAMPER, KEY_MODE_EXTI);
    printf("key init done\r\n");
    /* setup ethernet system(GPIOs, clocks, MAC, DMA, systick) */

    printf("enet init");
    enet_system_setup();
    printf("done \r\n");

    /* initilaize the LwIP stack */
    printf("lwip init ");
    lwip_stack_init();
    printf("done \r\n");

    /* initilaize the tcp server: telnet 8000 */
    printf("initilaize the tcp server: telnet 8000 ");
    hello_gigadevice_init();
    printf("done \r\n");
    /* initilaize the tcp client: echo 1026 */
    printf("initilaize the tcp client: echo 1026 ");
    tcp_client_init();
    printf("done \r\n");
    /* initilaize the udp: echo 1025 */
    printf("initilaize the udp: echo 1025 ");
    udp_echo_init();
    printf("done \r\n");

    printf("backtrace init");
    cm_backtrace_init("gd32f450zg_base", "1.00", "0.01");
    printf("done \r\n");

    EmbeddedCli *cli = getCliPointer();

    while (1) {

        if (pps_timestamp != uptime) {
            pps_timestamp = uptime;
            task_in_pps();
        }

#ifndef USE_ENET_INTERRUPT
        /* check if any packet received */
        if (enet_rxframe_size_get()) {
            /* process received ethernet packet */
            lwip_pkt_handle();
        }
#endif /* USE_ENET_INTERRUPT */

        /* handle periodic timers for LwIP */
#ifdef TIMEOUT_CHECK_USE_LWIP
        sys_check_timeouts();
        
#ifdef USE_DHCP
        lwip_dhcp_process_handle();
#endif /* USE_DHCP */ 

#else
        lwip_periodic_handle(g_localtime);
#endif /* TIMEOUT_CHECK_USE_LWIP */

        embeddedCliProcess(cli);
    }
}

/*!
    \brief      insert a delay time
    \param[in]  ncount: number of 10ms periods to wait for
    \param[out] none
    \retval     none
*/
void delay_10ms(uint32_t ncount) {
    /* capture the current local time */
    g_timedelay = g_localtime + ncount;

    /* wait until the desired delay finish */
    while (g_timedelay > g_localtime) {
    }
}

/*!
    \brief      updates the system local time
    \param[in]  none
    \param[out] none
    \retval     none
*/
void time_update(void) {
    g_localtime += SYSTEMTICK_PERIOD_MS;
    if (g_localtime % 1000 == 0) {
        uptime++;
    }
}

/* retarget the C library printf function to the USART */
int fputc(int ch, FILE *f) {
    usart_data_transmit(USART0, (uint8_t) ch);
    while (RESET == usart_flag_get(USART0, USART_FLAG_TBE));
    return ch;
}

#define PROMPT_CH_SIZE 4
static int8_t prompts[] = {'-', '\\', '|', '/'};

static void task_in_pps(void) {
    e_printf("%c uptime %lld\r\n", prompts[uptime % PROMPT_CH_SIZE], uptime);
    led_breath(uptime % 2);
}

